package com.watson.nettydemo.demo01;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;

/**
 * @author watson
 * @date 2021/7/21 16:42
 * @Description: TODO
 **/
public class SomeServer {
    public static void main(String[] args) {
        //用与处理客户端连接请求，将请求发送给childGroup的 EventLoop
        EventLoopGroup parentGroup = new NioEventLoopGroup();
        //用与处理客户端请求
        EventLoopGroup childGroup = new NioEventLoopGroup();
        try {
            //用户启动ServerChannel
            ServerBootstrap bootstrap = new ServerBootstrap();
            //指定eventLoopGroup
            bootstrap.group(parentGroup, childGroup)
                    //指定使用NIO进行通信，也可以使用其他方式
                    .channel(NioServerSocketChannel.class)
//                .handler() //parentGroup 里面使用的处理器
                    //指定处理器，childGroup中event Loop所绑定的线程要处理的处理器
//                    .childHandler(new SomeChannelInitializer());
                    //一般会在此处在用匿名内部类方式实现
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        //当Channel 初始创建完毕后就会触发该方法的执行，用于初始化Channel
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //从Channel中获取pipeline，创建channel的时候回忆起创建
                            ChannelPipeline pipeline = ch.pipeline();
                            //将HttpServerCodec处理器放入到pipeline的最后
                            //HttpServerCodec是HttpRequestDecoder和 HttpResponseEncoder的复合体
                            //HttpRequestDecoder：http请求解码器，将Channel中的ByteBuf数据解码为HttpRequest对象
                            //HttpResponseEncoder：http响应编码器，将httpResponse对象编码为将要在channel中发送的ByteBuf数据
                            pipeline.addLast("HttpServerCodec", new HttpServerCodec());
//        pipeline.addLast(new HttpServerCodec());
                            //将自定义的处理器放入到pipeline的最后
                            pipeline.addLast(new SomeServerHandler());

                        }

                    });

            //指定当前服务器所监听的端口号，bind方法的执行是异步的，//错误写法，不加sync()
            //sync() 会使bind()操作与后续的代码的执行由异步变成了同步
            ChannelFuture future = bootstrap.bind(6626).sync();
            System.out.println("服务器启动，端口号为9512");
            //关闭Channel
            //closeFuture的执行是异步的,当Channel调用关闭成功后才会触发closeFuture()的执行

            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //优雅关闭
            parentGroup.shutdownGracefully();
            childGroup.shutdownGracefully();
        }


    }
}
